package cn.mrcode.fd.blog.services.impl;

import cn.mrcode.fd.blog.cache.service.IArticleCache;
import cn.mrcode.fd.blog.common.BusConstant;
import cn.mrcode.fd.blog.dao.mapper.ArticleDetailsMapper;
import cn.mrcode.fd.blog.dao.mapper.ArticleMapper;
import cn.mrcode.fd.blog.dao.mappercu.ArticleCuMapper;
import cn.mrcode.fd.blog.dao.mappercu.ArticleDetailsCuMapper;
import cn.mrcode.fd.blog.dto.article.NewResData;
import cn.mrcode.fd.blog.dto.article.StatuRemarkJson;
import cn.mrcode.fd.blog.entity.Article;
import cn.mrcode.fd.blog.entity.ArticleDetails;
import cn.mrcode.fd.blog.entity.Category;
import cn.mrcode.fd.blog.entity.User;
import cn.mrcode.fd.blog.entityCu.ArticleCu;
import cn.mrcode.fd.blog.enu.ArticleError;
import cn.mrcode.fd.blog.exception.BlogException;
import cn.mrcode.fd.blog.services.IArticleService;
import cn.mrcode.fd.blog.services.IBlogConfigService;
import cn.mrcode.fd.blog.services.ICategoryService;
import cn.mrcode.fd.blog.services.ITagService;
import cn.mrcode.fd.utils.mybatis.page.Page;
import cn.mrcode.fd.utils.mybatis.page.PageHelper;
import cn.mrcode.fd.utils.mybatis.page.PageHelperUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author zhuqiang
 * @version V1.0
 * @date 2015/12/3 22:19
 */
@Service
public class ArticleServiceImpl implements IArticleService {
    @Autowired
    private ArticleMapper articleMapper;
    @Autowired
    private ArticleCuMapper articleCuMapper;
    @Autowired
    private ArticleDetailsMapper articleDetailsMapper;
    @Autowired
    private ArticleDetailsCuMapper articleDetailsCuMapper;
    @Autowired
    private ITagService iTagService;
    @Autowired
    private ICategoryService iCategoryService;
    @Autowired
    private IBlogConfigService iBlogConfigService;
    @Autowired
    private IArticleCache iArticleCache;
    @Override
    public List<Article> queryAll() {
        return articleCuMapper.selectSelective(null);
    }

    @Override
    public Page<Article> queryAllPage(Page<Article> page) {
        page = page == null ? new Page<Article>() : page;
        PageHelper.setLocalPage(page);
        List<Article> articles = articleCuMapper.selectSelective(null);
        page.setResults(articles);
        PageHelperUtil.removeLocalPage();
        return page;
    }

    @Override
    public Page<ArticleCu> queryAll(Page<ArticleCu> page, String account) {
        page = page == null ? new Page<ArticleCu>() : page;
        PageHelper.setLocalPage(page);
        List<ArticleCu> articles = articleCuMapper.selectByAccount(account);
        page.setResults(articles);
        PageHelperUtil.removeLocalPage();
        return page;
    }
    @Override
    public Page<ArticleCu> queryAll(Page<ArticleCu> page, String account,Integer articleStatus) {
        page = page == null ? new Page<ArticleCu>() : page;
        PageHelper.setLocalPage(page);
        ArticleCu params = new ArticleCu();
        params.setUserAccount(account);
        params.setStatus(articleStatus);
        params.setIsDel(false);
        List<ArticleCu> articles = articleCuMapper.selectCuSelective(params);
        for (ArticleCu article : articles) {
            article.setStatusName(BusConstant.ArticleStatus.enMap.get(article.getStatus()));
        }
        page.setResults(articles);
        PageHelperUtil.removeLocalPage();
        return page;
    }
    @Override
    public Page<ArticleCu> queryAllOrderBy(Page<ArticleCu> page, String orderBy, String sortType) {
        page = page == null ? new Page<ArticleCu>() : page;
        PageHelper.setLocalPage(page);
        List<ArticleCu> articles = articleCuMapper.selectCuSelectiveOrderBy(null,orderBy,sortType);
        page.setResults(articles);
        PageHelperUtil.removeLocalPage();
        return page;
    }
    @Override
    public Article _findById(String id) {
        return articleMapper.selectByPrimaryKey(id);
    }
    @Override
    public ArticleCu findById(String id) {
        ArticleCu articleCu = articleCuMapper.selectArticleDetailById(id);
        if (articleCu == null) {
            return null;
        }
        articleCu.setTagNameList(handerTagNames(articleCu.getTagNames()));
        articleCu.setCategorys(iCategoryService.findArticleCat(id));
        return articleCu;
    }

    /**
     * 处理标签
     * @param tagNames 标签名,按逗号隔开
     * @return
     */
    private List<String> handerTagNames(String tagNames) {
        if (StringUtils.isNotBlank(tagNames)) { //处理标签
            String[] tagArr = tagNames.split(",");
            List<String> tagNameList = new ArrayList<>();
            for (String tagName : tagArr) {
                tagNameList.add(tagName);
            }
            return tagNameList;
        }
        return null;
    }

    @Override
    public Long findReadNumById(String articleId) {
        return articleCuMapper.selectReadNumById(articleId);
    }

    @Override
    public String loadDetailsBody(String articleId) {
        String body = articleDetailsCuMapper.selectBody(articleId);
        return body;
    }

    @Override
    @Transactional
    public void mod(ArticleCu articleCu, String userAccount) {
        String newTagNames = articleCu.getTagNames();
        String id = articleCu.getId(); //文章id
        Article db_article = articleMapper.selectByPrimaryKey(id);
        if (db_article == null) {
            throw new RuntimeException("博文id不存在");
        }
        // 处理标签
        iTagService.handerTag(id, db_article.getTagNames(), newTagNames);
        // 处理分类
        iCategoryService.handerCategory(id, userAccount, articleCu.getCategoryNames());

        Article article = new Article();
        article.setId(id);
        article.setModTime(new Date());
        article.setTitle(articleCu.getTitle());
        article.setTagNames(articleCu.getTagNames());
        article.setSummary(articleCu.getSummary());
        article.setSummaryImg(articleCu.getSummaryImg());
        articleMapper.updateByPrimaryKeySelective(article);


        ArticleDetails record = new ArticleDetails();
        record.setArticleId(id);
        record.setBody(articleCu.getBody());
        articleDetailsCuMapper.updateByArticleIdSelective(record);

        Article cache_article = articleMapper.selectByPrimaryKey(id);
        iArticleCache.upWeekNewest(cache_article);
        iArticleCache.upWeekHotTop(cache_article);
    }

    @Override
    @Transactional
    public String insert(ArticleCu articleCu, User user) throws Exception {
        String newTagNames = articleCu.getTagNames();

        Article article = new Article();
        article.setId(iArticleCache.genArticleId());
        article.setTitle(articleCu.getTitle());
        article.setUserId(user.getId());
        article.setUserAccount(user.getAccount());
        article.setTagNames(newTagNames); //标签列表
        article.setStatus(BusConstant.ArticleStatus.NORMAL); //文章状态
        article.setSummary(articleCu.getSummary());
        article.setSummaryImg(articleCu.getSummaryImg());
        article.setCreateBy(user.getId());
        article.setCreateTime(new Date());
        articleMapper.insertSelective(article);

        ArticleDetails record = new ArticleDetails();
        record.setId(article.getId());
        record.setBody(articleCu.getBody());
        record.setArticleId(article.getId());
        articleDetailsMapper.insertSelective(record);
        // 处理标签
        iTagService.handerTag(article.getId(),"", newTagNames);
        // 处理分类
        iCategoryService.handerCategory(article.getId(), user.getAccount(), articleCu.getCategoryNames());

        iBlogConfigService.updateAddArticleNum(user.getId());

        iArticleCache.addWeekNewest(articleMapper.selectByPrimaryKey(article.getId()));
        return article.getId();
    }

    @Override
    public ArticleCu find(String account, String id) {
        ArticleCu params = new ArticleCu();
        params.setUserAccount(account);
        params.setId(id);
        List<ArticleCu> articles = articleCuMapper.selectCuSelective(params);
        ArticleCu articleCu = articles.get(0);
        if (articleCu != null) {
            List<Category> categorysAll = iCategoryService.findAllByAccount(account);
            articleCu.setCategorysAll(categorysAll);  //设置所有的分类列表

            List<Category> categorys = iCategoryService.findArticleCat(articleCu.getId());
            //设置该文章所引用的文类
            StringBuffer categoryNames = new StringBuffer();
            for (int i = 0; i < categorys.size(); i++) {
                Category category = categorys.get(i);
                categoryNames.append(category.getName());
                if (i != categorys.size() - 1) {
                    categoryNames.append(",");
                }
            }
            articleCu.setCategoryNames(categoryNames.toString()); //分类列表名称
        }
        return articleCu;
    }


    @Override
    public ArticleCu createPre(String userAccount) {
        ArticleCu articleCu = new ArticleCu();
        articleCu.setUserAccount(userAccount);
        List<Category> categorysAll = iCategoryService.findAllByAccount(userAccount);
        articleCu.setCategorysAll(categorysAll);  //设置所有的分类列表
        return articleCu;
    }

    @Override
    public List<ArticleCu> top(int i) {
        return  articleCuMapper.selectTop(i);
    }

    @Override
    public List<ArticleCu> top(int i,String userAccount) {
        return  articleCuMapper.selectUserTop(i,userAccount);
    }

    @Override
    @Transactional
    public String delete(String articleId, String userAccount, String userId, int currentStatus, int toNewStatus, String statusRemark) throws Exception {
        if(!BusConstant.ArticleStatus.isCanTransfer(currentStatus,toNewStatus)){
            return "非法操作：文章状态转移非法/异常";
        }
        ArticleCu params = new ArticleCu();
        params.setUserAccount(userAccount);
        params.setId(articleId);
        List<ArticleCu> articles = articleCuMapper.selectCuSelective(params);
        if(CollectionUtils.isEmpty(articles)){
            return "该文章不存在！";
        }

        ArticleCu articleCu = articles.get(0);
        Integer status = articleCu.getStatus();
        if(status.intValue() == currentStatus){
            switch (toNewStatus){
                case BusConstant.ArticleStatus.AUDIT:
                    break;
                case BusConstant.ArticleStatus.NORMAL:
                    break;
                case BusConstant.ArticleStatus.DRAFTS:
                    break;
                case BusConstant.ArticleStatus.RECYCLE:
                    del_recycle(articleCu,statusRemark);
                    iArticleCache.removeWeekNewest(articleCu.getId());
                    break;
                case BusConstant.ArticleStatus.SHIELD:
                    break;
                case BusConstant.ArticleStatus.DEL:
                    del_thorough(articleCu);
                    iArticleCache.removeWeekNewest(articleCu.getId());
                    break;
            }

        }else{
            return "文章状态异常，请刷新后重试";
        }

        // 还需要清理标签索引什么的？ 这里只清除彻底删除的文章索引
        return null;
    }

    /**
     * 彻底删除
     */
    private void del_thorough(ArticleCu articleCu) throws Exception {
        String id = articleCu.getId();
        //删除分类引用
        iCategoryService.delRef(id);
        //删除标签引用/更新标签计数器
        iTagService.delRef(id);
        //删除文章统计数量
        iBlogConfigService.delArticleNum(articleCu.getUserId(),1);
        //删除文章详情
        articleDetailsCuMapper.deleteByArticleId(id);
        //删除文章
        articleMapper.deleteByPrimaryKey(id);
    }
    /**
     * 删除文章到回收站
     * @param articleCu db数据库查询出来的文章
     * @param statusRemark
     */
    private void del_recycle(ArticleCu articleCu,String statusRemark) {
        Integer currentStatu = articleCu.getStatus();
        Article record = new Article();
        record.setId(articleCu.getId());
        record.setStatus(BusConstant.ArticleStatus.RECYCLE);
        record.setStatusRemark(getArticleStatusRemark(currentStatu,BusConstant.ArticleStatus.RECYCLE,articleCu.getStatusRemark(),statusRemark));
        record.setModTime(new Date());
        record.setModBy(articleCu.getCreateBy());
        articleMapper.updateByPrimaryKeySelective(record);
        iArticleCache.removeAllTop(articleCu.getId());
    }

    /**
     * 获取状态转义备注json串
     * @param currentStatu
     * @param toNewStatus
     * @param oldStatusRemark
     * @param newStatusRemark
     */
    private String getArticleStatusRemark(int currentStatu, int toNewStatus,String oldStatusRemark,String newStatusRemark) {
        if(StringUtils.isNotBlank(newStatusRemark)){
            if(StringUtils.isNotBlank(oldStatusRemark)){
                List<StatuRemarkJson> statuRemarkJsons = JSONObject.parseArray(oldStatusRemark, StatuRemarkJson.class);
                StatuRemarkJson srj = new StatuRemarkJson();
                srj.setDate(DateFormatUtils.format(new Date(),"yyyy-MM-dd HH:mm:ss"));
                srj.setOldStatu(currentStatu);
                srj.setNewStatu(toNewStatus);
                srj.setRemark(newStatusRemark);
                statuRemarkJsons.add(srj);
                return JSON.toJSONString(statuRemarkJsons);
            }else{
                List<StatuRemarkJson> statuRemarkJsons = new ArrayList<>();
                StatuRemarkJson srj = new StatuRemarkJson();
                srj.setDate(DateFormatUtils.format(new Date(),"yyyy-MM-dd HH:mm:ss"));
                srj.setOldStatu(currentStatu);
                srj.setNewStatu(toNewStatus);
                srj.setRemark(newStatusRemark);
                statuRemarkJsons.add(srj);
                return JSON.toJSONString(statuRemarkJsons);
            }
        }
        return null;
    }


    @Override
    public Page<ArticleCu> queryAllByCategory(Page<ArticleCu> page, String categoryId) {
        PageHelper.setLocalPage(page);
        List<ArticleCu> articles = articleCuMapper.selectListByCategory(categoryId);
        page.setResults(articles);
        PageHelperUtil.removeLocalPage();
        return page;
    }

    @Override
    @Transactional
    public String recovery(String articleId, String account, String modBy) {
        ArticleCu params = new ArticleCu();
        params.setUserAccount(account);
        params.setId(articleId);
        List<ArticleCu> articles = articleCuMapper.selectCuSelective(params);
        if(CollectionUtils.isEmpty(articles)){
            return "该文章不存在！";
        }
        ArticleCu articleCu = articles.get(0);
        Integer status = articleCu.getStatus();
        if(status.intValue() == BusConstant.ArticleStatus.RECYCLE){
            Article record = new Article();
            record.setId(articleCu.getId());
            record.setStatus(BusConstant.ArticleStatus.NORMAL);
           /* record.setStatusRemark(getArticleStatusRemark(status.intValue(),BusConstant.ArticleStatus.NORMAL,articleCu.getStatusRemark(),account + " 发起恢复操作"));*/
            record.setModTime(new Date());
            record.setModBy(articleCu.getCreateBy());
            articleMapper.updateByPrimaryKeySelective(record);
        }else{
            return "文章状态异常，请刷新后重试";
        }
        return null;
    }

    @Override
    public NewResData newData(String userAccount) throws BlogException{
        try{
            List<Category> categorysAll = iCategoryService.findAllByAccount(userAccount);
            NewResData newResData = new NewResData(true);
            newResData.setUserAccount(userAccount);
            newResData.setCategorysAll(categorysAll);
//            String newbody = "[TOCM]bowtie: hello,mrcode blog!";
//            newResData.setNewbody(newbody);
            return newResData;
        }catch (Exception e){
            throw new BlogException(ArticleError.SYSTEM_ERROR.getInfo());
        }
    }
}
